import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;

/**
 * @author sjw
 * @className NewTime
 * @date 2022/4/24 15:58
 * @description: TODO
 */
public class NewTime {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(Integer.MAX_VALUE);
//        LocalDateTime now = LocalDateTime.now();
//        System.out.println(now);
//
//        System.out.println("当前精确时间：" + now.getYear() + "-" + now.getMonthValue() + "-" + now.getDayOfMonth() + " " + now.getHour() + "-" + now.getMinute() + "-" + now.getSecond());
//
//
//        String a = "您好！您的房源信息发生变更，请登陆千家找房app进行确认。如果信息有误，请联系${username}电话：${userTel}修正信息。";
//        Map<String, String> m = new HashMap<>();
//        m.put("username", "111");
//        m.put("userTel", "123");
//        m.put("userTel1", "123");
//        for (Map.Entry<String, String> entry : m.entrySet()) {
//            int index = a.indexOf("${" + entry.getKey() + "}");
//            System.out.println(index + "   " + entry.getKey() + "   " + entry.getValue());
//
//        }
        int t=10;
        NewTime newTime=NewTime.Instance();
        CountDownLatch countDownLatch=new CountDownLatch(t);
        for (int i=0; i<t; i++){
            new Thread(()->{

                try {
                    Object s= newTime.exec("123",()->{
                        System.out.println("exec ----");
                        try {
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return System.currentTimeMillis();
                    });
                    System.out.println(s);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }).start();
            countDownLatch.countDown();
        }
        countDownLatch.await();


    }


    private Lock lock;
    private Map<String, MyCall> map;


    private static class MyCall {
        private Object res;
        private CountDownLatch latch;

        public MyCall(Integer i) {
            latch = new CountDownLatch(i);
        }
    }

    private static class CallRes {
        private MyCall call;
        private boolean done;

        public CallRes(MyCall call, boolean done) {
            this.call = call;
            this.done = done;
        }

    }

    public NewTime(){
        this.lock=new ReentrantLock();
        this.map=new HashMap<>();
    }

    public static NewTime Instance() {
        return new NewTime();
    }

    private Object exec(String key, Supplier<Object> fn) throws InterruptedException {
        CallRes res=createCall(key);
        if(res.done)
        {
//            System.out.println("exec done");
            return res.call.res;
        }
        makeCall(res.call,key,fn);
        return res.call.res;
    }


    private CallRes createCall(String key) throws InterruptedException {
        lock.lock();
        MyCall call = map.get(key);
        if (call != null) {
            lock.unlock();
            // 阻塞
            call.latch.await();
            return new CallRes(call, true);
        }
        call = new MyCall(1);
        map.put(key, call);
        lock.unlock();
        return new CallRes(call, false);
    }

    private void makeCall(MyCall call, String key,Supplier<Object> fn) {
        call.res=fn.get();
        lock.lock();
        map.remove(key);
        lock.unlock();
        call.latch.countDown();
    }

}
